package net.wanho.service.impl;

import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.RequiredArgsConstructor;
import net.wanho.constant.AuthConstant;
import net.wanho.constant.UserConstant;
import net.wanho.dto.AddAuthDTO;
import net.wanho.dto.AuthInfoDTO;
import net.wanho.mapper.*;
import net.wanho.po.AuthInfo;
import net.wanho.po.RoleAuth;
import net.wanho.service.AuthInfoService;
import net.wanho.service.UserInfoService;
import net.wanho.util.ThreadUtil;
import net.wanho.vo.MenuVo;
import org.springframework.beans.BeanUtils;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;

import java.time.LocalDateTime;
import java.util.Collections;
import java.util.List;
import java.util.stream.Collectors;

/**
* @author Administrator
* @description 针对表【auth_info(权限表)】的数据库操作Service实现
* @createDate 2025-04-28 11:41:58
*/
@Service
@RequiredArgsConstructor
public class AuthInfoServiceImpl extends ServiceImpl<AuthInfoMapper, AuthInfo>
        implements AuthInfoService{

    private final RedisTemplate<String,Object> redisTemplate;
    private final ObjectMapper objectMapper;

    private final UserInfoMapper userInfoMapper;

    private final RoleMapper roleMapper;

    private final RoleAuthMapper roleAuthMapper;

    private final AuthInfoMapper authInfoMapper;

    private final UserRoleMapper userRoleMapper;

    @Override
    public List<MenuVo> findMenus() {
        Integer id = ThreadUtil.getId();

        List<MenuVo> menus = (List<MenuVo>) redisTemplate.opsForValue().get(UserConstant.MENU_PREFIX + id);
        if (ObjectUtil.isNotEmpty(menus)) {
            return menus;
        }

        List<Integer> authIds = authInfoMapper.selectByUserId(id);
        List<AuthInfo> authInfos = authInfoMapper.selectAll(authIds);
        menus = authInfos.stream()
                .filter(item -> item.getParentId().equals(0))
                .map(item -> {
                    MenuVo menuVo = new MenuVo();
                    BeanUtils.copyProperties(item, menuVo);
                    findChildren(menuVo, authInfos);
                    return menuVo;
                })
                .collect(Collectors.toList());

        redisTemplate.opsForValue().set(UserConstant.MENU_PREFIX + id, menus, UserConstant.MENU_EXPIRE, UserConstant.MENU_TIME_UNIT);

        return menus;
    }

    @Override
    public List<Integer> selectByUserId(Integer userId) {
        return authInfoMapper.getByUserId(userId);
    }

    @Override
    public List<AuthInfo> findAll() {
        // 获取所有权限
        List<AuthInfo> authInfos = authInfoMapper.selectList(null);
        // 获取一级权限
        List<AuthInfo> list = authInfos.stream()
                .filter(item -> item.getParentId().equals(0))
                .map(item -> {
                    findchild(item, authInfos);
                    return item;
                })
                .collect(Collectors.toList());
        return list;
    }

    @Override
    public Boolean nameCheck(String authName) {
        // 查询权限名是否重复
        AuthInfo authInfo = authInfoMapper.selectByName(authName);
        return authInfo == null;
    }

    @Override
    public Boolean urlCheck(String authUrl) {
        // 查询权限名是否重复
        AuthInfo authInfo = authInfoMapper.selectByUrl(authUrl);
        return authInfo == null;
    }

    @Override
    public Boolean selectByCode(String authCode) {
        AuthInfo authInfo = authInfoMapper.selectByCode(authCode);
        return authInfo == null;
    }

    @Override
    public void addAuth(AddAuthDTO addAuthDTO) {
        AuthInfo authInfo = new AuthInfo();
        BeanUtils.copyProperties(addAuthDTO, authInfo);
        LocalDateTime now = LocalDateTime.now();
        authInfo.setCreateTime(now);
        authInfo.setUpdateTime(now);
        Integer id = ThreadUtil.getId();
        authInfo.setCreateBy(id);
        authInfo.setAuthState(AuthConstant.ENABLE);
        authInfoMapper.insert(authInfo);
    }

    @Override
    public void enableAuth(Integer id) {
        AuthInfo authInfo = authInfoMapper.selectById(id);
        authInfo.setAuthState(AuthConstant.ENABLE);
        LocalDateTime now = LocalDateTime.now();
        authInfo.setUpdateTime(now);
        Integer id1 = ThreadUtil.getId();
        authInfo.setUpdateBy(id1);
        authInfoMapper.updateById(authInfo);
    }

    @Override
    public void disableAuth(Integer id) {
        AuthInfo authInfo = authInfoMapper.selectById(id);
        authInfo.setAuthState(AuthConstant.DISABLE);
        LocalDateTime now = LocalDateTime.now();
        authInfo.setUpdateTime(now);
        Integer id1 = ThreadUtil.getId();
        authInfo.setUpdateBy(id1);
        authInfoMapper.updateById(authInfo);
    }

    @Override
    public void updateAuth(AuthInfoDTO authInfoDTO) {
        AuthInfo authInfo = new AuthInfo();
        BeanUtils.copyProperties(authInfoDTO, authInfo);
        LocalDateTime now = LocalDateTime.now();
        authInfo.setUpdateTime(now);
        Integer id1 = ThreadUtil.getId();
        authInfo.setUpdateBy(id1);
        authInfoMapper.updateById(authInfo);
    }

    private void findchild(AuthInfo item, List<AuthInfo> authInfos) {
        List<AuthInfo> collect = authInfos.stream()
                .filter(item2 -> item2.getParentId().equals(item.getAuthId()))
                .map(item2 -> {
                    findchild(item2, authInfos);
                    return item2;
                })
                .collect(Collectors.toList());
        item.setChildAuth(collect);
    }

    private void findChildren(MenuVo menuVo, List<AuthInfo> authInfos) {
        List<MenuVo> collect = authInfos.stream()
                .filter(item2 -> item2.getParentId().equals(menuVo.getAuthId()))
                .map(item2 -> {
                    MenuVo menuVo1 = new MenuVo();
                    BeanUtils.copyProperties(item2, menuVo1);
                    findChildren(menuVo1, authInfos);
                    return menuVo1;
                })
                .collect(Collectors.toList());
        menuVo.setChildAuth(collect);
    }


}




